package com.dlc.shop.user.common.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dlc.shop.bean.app.dto.CouponDto;
import com.dlc.shop.bean.enums.JumpType;
import com.dlc.shop.bean.enums.ProdStatusEnums;
import com.dlc.shop.bean.enums.ShopStatus;
import com.dlc.shop.bean.event.PopupCouponInfoEvent;
import com.dlc.shop.bean.model.*;
import com.dlc.shop.bean.vo.ShopCustomerVO;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.constants.CacheNames;
import com.dlc.shop.common.enums.StatusEnum;
import com.dlc.shop.common.enums.UserLevelType;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.util.BeanUtil;
import com.dlc.shop.common.util.PageParam;
import com.dlc.shop.common.util.RedisUtil;
import com.dlc.shop.service.CategoryService;
import com.dlc.shop.service.ProductService;
import com.dlc.shop.service.ShopDetailService;
import com.dlc.shop.service.ShopRenovationService;
import com.dlc.shop.user.common.bo.CategoryLinkBO;
import com.dlc.shop.user.common.bo.JumpUrlBO;
import com.dlc.shop.user.common.dao.CostPerPopupMapper;
import com.dlc.shop.user.common.dao.UserLevelMapper;
import com.dlc.shop.user.common.dto.CostPerPopupDTO;
import com.dlc.shop.user.common.enums.PopupStatusEnum;
import com.dlc.shop.user.common.enums.PopupUserTypeEnum;
import com.dlc.shop.user.common.enums.PushFrequencyEnum;
import com.dlc.shop.user.common.model.CostPerPopup;
import com.dlc.shop.user.common.model.PopupRelate;
import com.dlc.shop.user.common.model.PopupUserLog;
import com.dlc.shop.user.common.model.UserLevel;
import com.dlc.shop.user.common.service.CostPerPopupService;
import com.dlc.shop.user.common.service.PopupRelateService;
import com.dlc.shop.user.common.service.PopupUserLogService;
import com.dlc.shop.user.common.vo.CostPerPopupVO;
import com.dlc.shop.user.common.vo.PopupRelateVO;
import lombok.AllArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author TRACK
 */
@Service
@AllArgsConstructor
public class CostPerPopupServiceImpl extends ServiceImpl<CostPerPopupMapper, CostPerPopup> implements CostPerPopupService {

    private final CostPerPopupMapper costPerPopupMapper;
    private final UserLevelMapper userLevelMapper;
    private final PopupRelateService popupRelateService;
    private final PopupUserLogService popupUserLogService;
    private final ProductService productService;
    private final ApplicationEventPublisher eventPublisher;
    private final CategoryService categoryService;
    private final ShopDetailService shopDetailService;
    private final ShopRenovationService shopRenovationService;

    @Override
    public IPage<CostPerPopupVO> page(PageParam<CostPerPopupVO> pageDTO, CostPerPopupDTO costPerPopupDTO) {
        return costPerPopupMapper.page(pageDTO, costPerPopupDTO);
    }

    @Override
    @Cacheable(cacheNames = "popupListByShopId", key = "#shopId")
    public List<CostPerPopupVO> listByShopId(Long shopId) {
        return costPerPopupMapper.listByShopId(shopId);
    }

    @Override
    public CostPerPopupVO getShopPopupByCondition(ShopCustomerVO shopCustomerVO, Integer pageType, Long shopId, String userId, String uuid) {
        CostPerPopupServiceImpl costPerPopupService = (CostPerPopupServiceImpl) AopContext.currentProxy();
        List<CostPerPopupVO> costPerPopupList = costPerPopupService.listByShopId(shopId);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return null;
        }
        // 校验时间
        Iterator<CostPerPopupVO> iterator = costPerPopupList.iterator();
        while (iterator.hasNext()) {
            CostPerPopupVO costPerPopup = iterator.next();
            // 校验信息
            if (checkInfo(shopCustomerVO, pageType, costPerPopup)) {
                iterator.remove();
                continue;
            }
            // 校验是否为跳转优惠券并且用户领取过并且有库存
            if (checkCoupon(userId, iterator, costPerPopup)) {
                iterator.remove();
                continue;
            }
            if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.EVERY_TIME.value())) {
                // 每次进入直接返回
                return costPerPopup;
            }
            if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.ONCE.value())) {
                // 永久一次的校验是否曾推送过
                List<PopupUserLog> list = popupUserLogService.getByCondition(userId, uuid, costPerPopup);
                if (CollUtil.isEmpty(list)) {
                    return costPerPopup;
                }
                // 推送过了
                iterator.remove();
                continue;
            }
            checkWeek(iterator, costPerPopup);
        }
        if (CollUtil.isEmpty(costPerPopupList)) {
            return null;
        }
        // 校验弹窗日志
        for (CostPerPopupVO costPerPopup : costPerPopupList) {
            List<PopupUserLog> list = popupUserLogService.getByCondition(userId, uuid, costPerPopup);
            if (CollUtil.isEmpty(list)) {
                return costPerPopup;
            }
        }
        return null;
    }

    private static boolean checkInfo(ShopCustomerVO shopCustomerVO, Integer pageType, CostPerPopupVO costPerPopup) {
        if (!Objects.equals(costPerPopup.getPageType(), pageType)) {
            // 页面类型不一致
            return true;
        }
        if (PopupUserTypeEnum.isShopUser(costPerPopup.getUserType()) && Objects.isNull(shopCustomerVO)) {
            // 游客不属于店铺客户或会员
            return true;
        }
        if (Objects.nonNull(shopCustomerVO) && Objects.equals(shopCustomerVO.getLevelType(), -1)
                && Objects.equals(costPerPopup.getUserType(), PopupUserTypeEnum.SHOP_VIP.value())) {
            // 店铺客户不属于店铺会员
            return true;
        }
        if (Objects.nonNull(shopCustomerVO) && Objects.equals(shopCustomerVO.getLevelType(), 0)
                && Objects.equals(costPerPopup.getUserType(), PopupUserTypeEnum.SHOP_USER.value())) {
            List<PopupRelateVO> popupRelateList = costPerPopup.getPopupRelateList();
            if (CollUtil.isEmpty(popupRelateList)) {
                // 没有关联会员
                return true;
            }
            List<Long> userLevelIds = popupRelateList.stream().map(PopupRelateVO::getUserLevelId).toList();
            if (!userLevelIds.contains(shopCustomerVO.getLevelId())) {
                // 没有关联会员
                return true;
            }
        }
        return false;
    }

    @Override
    public CostPerPopupVO getSysPopupByCondition(User user, Integer pageType, String uuid) {
        List<Long> levelIds = new ArrayList<>(Collections.singletonList(user.getLevelId()));
        if (Objects.equals(user.getLevelType(), UserLevelType.VIP.value())) {
            levelIds.add(user.getVipLevelId());
        }
        CostPerPopupServiceImpl costPerPopupService = (CostPerPopupServiceImpl) AopContext.currentProxy();
        List<CostPerPopupVO> costPerPopupList = costPerPopupService.listByShopId(Constant.PLATFORM_SHOP_ID);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return null;
        }
        // 校验时间
        Iterator<CostPerPopupVO> iterator = costPerPopupList.iterator();
        while (iterator.hasNext()) {
            CostPerPopupVO costPerPopup = iterator.next();
            // 校验信息
            if (checkSysInfo(user, pageType, costPerPopup)) {
                iterator.remove();
                continue;
            }
            // 校验是否为跳转优惠券并且用户领取过
            if (checkCoupon(user.getUserId(), iterator, costPerPopup)) {
                iterator.remove();
                continue;
            }
            if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.EVERY_TIME.value())) {
                // 每次进入直接返回
                return costPerPopup;
            }
            if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.ONCE.value())) {
                // 永久一次的校验是否曾推送过
                List<PopupUserLog> list = popupUserLogService.getByCondition(user.getUserId(), uuid, costPerPopup);
                if (CollUtil.isEmpty(list)) {
                    return costPerPopup;
                }
                // 推送过了
                iterator.remove();
            }
            checkWeek(iterator, costPerPopup);
        }
        if (CollUtil.isEmpty(costPerPopupList)) {
            return null;
        }
        // 校验弹窗日志
        for (CostPerPopupVO costPerPopup : costPerPopupList) {
            List<PopupUserLog> list = popupUserLogService.getByCondition(user.getUserId(), uuid, costPerPopup);
            if (CollUtil.isEmpty(list)) {
                return costPerPopup;
            }
        }
        return null;
    }

    private static boolean checkSysInfo(User user, Integer pageType, CostPerPopupVO costPerPopup) {
        if (!Objects.equals(costPerPopup.getPageType(), pageType)) {
            // 页面类型不一致
            return true;
        }
        if (PopupUserTypeEnum.isSysUser(costPerPopup.getUserType()) && Objects.isNull(user)) {
            // 游客不属于会员
            return true;
        }
        if (Objects.nonNull(user) && PopupUserTypeEnum.isSysUser(costPerPopup.getUserType())) {
            List<PopupRelateVO> popupRelateList = costPerPopup.getPopupRelateList();
            if (CollUtil.isEmpty(popupRelateList)) {
                // 没有关联会员
                return true;
            }
            List<Long> userLevelIds = popupRelateList.stream().map(PopupRelateVO::getUserLevelId).toList();
            if (Objects.equals(PopupUserTypeEnum.FREE_USER.value(), costPerPopup.getUserType()) && !userLevelIds.contains(user.getLevelId())) {
                // 没有关联免费会员
                return true;
            }
            if (Objects.equals(PopupUserTypeEnum.PAY_USER.value(), costPerPopup.getUserType()) && !userLevelIds.contains(user.getVipLevelId())) {
                // 没有关联付费会员
                return true;
            }
        }
        return false;
    }

    private boolean checkCoupon(String userId, Iterator<CostPerPopupVO> iterator, CostPerPopupVO costPerPopup) {
        // 如果是提示领取同一张优惠券的，则用户领取完之后不再推送
        JumpUrlBO jumpUrlBO = JSON.parseObject(costPerPopup.getJumpUrl(), JumpUrlBO.class);
        if (!Objects.equals(jumpUrlBO.getType(), JumpType.COUPON.value())) {
            return false;
        }
        Long couponId = Long.parseLong(jumpUrlBO.getLink());
        PopupCouponInfoEvent popupCouponInfoEvent = new PopupCouponInfoEvent(couponId);
        if (Objects.nonNull(userId)) {
            popupCouponInfoEvent.setUserId(userId);
        }
        eventPublisher.publishEvent(popupCouponInfoEvent);
        if (Objects.nonNull(userId)) {
            Long receiveCount = popupCouponInfoEvent.getReceiveCount();
            if (receiveCount > 0) {
                // 优惠券领取过
                return true;
            }
        }
        // 校验库存
        Integer stock = popupCouponInfoEvent.getStock();
        return stock == null || stock < 1;
    }

    private static void checkWeek(Iterator<CostPerPopupVO> iterator, CostPerPopupVO costPerPopup) {
        if (Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.CUSTOM.value()) && StrUtil.isNotBlank(costPerPopup.getWeekFrequency())) {
            List<String> weeks = Arrays.stream(costPerPopup.getWeekFrequency().split(StrUtil.COMMA)).toList();
            int week = DateUtil.dayOfWeek(new Date());
            if (!weeks.contains(String.valueOf(week))) {
                iterator.remove();
            }
        }
    }

    @Override
    @Cacheable(cacheNames = "popup", key = "#popupId")
    public CostPerPopupVO getByPopupId(Long popupId) {
        CostPerPopup popup = costPerPopupMapper.getByPopupId(popupId);
        CostPerPopupVO popupVO = BeanUtil.map(popup, CostPerPopupVO.class);
        List<PopupRelate> relateList = popupRelateService.getByPopupId(popupId);
        if (CollUtil.isNotEmpty(relateList)) {
            List<PopupRelateVO> popupRelateVOList = BeanUtil.mapAsList(relateList, PopupRelateVO.class);
            popupVO.setPopupRelateList(popupRelateVOList);
        }
        return popupVO;
    }

    @Override
    public void handleInfo(CostPerPopupVO popup) {
        if (CollUtil.isEmpty(popup.getPopupRelateList())) {
            return;
        }
        List<PopupRelateVO> popupRelateVOList = popup.getPopupRelateList();
        // 组装会员等级数据
        // 店铺会员
        boolean isShopLevel = !Objects.equals(popup.getShopId(), Constant.PLATFORM_SHOP_ID)
                && (Objects.equals(popup.getUserType(), PopupUserTypeEnum.SHOP_VIP.value()));
        if (isShopLevel) {
            List<Long> userLevelIds = popupRelateVOList.stream().map(PopupRelateVO::getUserLevelId).filter(id -> Objects.nonNull(id)).collect(Collectors.toList());
            List<UserLevel> userLevels = userLevelMapper.listUserLevelIds(userLevelIds, popup.getShopId());
            setLevelName(popupRelateVOList, userLevels);
        }

        // 平台会员
        boolean isLevel = Objects.equals(popup.getShopId(), Constant.PLATFORM_SHOP_ID)
                && (Objects.equals(popup.getUserType(), PopupUserTypeEnum.FREE_USER.value())
                || Objects.equals(popup.getUserType(), PopupUserTypeEnum.PAY_USER.value()));
        if (isLevel) {
            List<Long> userLevelIds = popupRelateVOList.stream().map(PopupRelateVO::getUserLevelId).collect(Collectors.toList());
            List<UserLevel> userLevels = userLevelMapper.listUserLevelIds(userLevelIds, Constant.PLATFORM_SHOP_ID);
            setLevelName(popupRelateVOList, userLevels);
        }
    }

    private static void setLevelName(List<PopupRelateVO> popupRelateVOList, List<UserLevel> userLevels) {
        Map<Long, String> levelMap = userLevels.stream().collect(Collectors.toMap(UserLevel::getId, UserLevel::getLevelName));
        Iterator<PopupRelateVO> iterator = popupRelateVOList.iterator();
        while (iterator.hasNext()) {
            PopupRelateVO popupRelateVO = iterator.next();
            String levelName = levelMap.get(popupRelateVO.getUserLevelId());
            if (StrUtil.isBlank(levelName)) {
                continue;
            }
            popupRelateVO.setLevelName(levelName);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "popupListByShopId", key = "#costPerPopup.shopId")
    public void insert(CostPerPopup costPerPopup) {
        setTime(costPerPopup);
        checkJumpUrl(costPerPopup);
        List<Long> userLevelIds = checkAndGetUserLevelIds(costPerPopup);
        costPerPopupMapper.save(costPerPopup);
        List<PopupRelate> popupRelates = getPopupRelates(costPerPopup, userLevelIds);
        if (CollUtil.isNotEmpty(popupRelates)) {
            popupRelateService.saveBatch(popupRelates);
        }
    }
    private void checkJumpUrl(CostPerPopup costPerPopup) {
        JumpUrlBO jumpUrlBO = JSON.parseObject(costPerPopup.getJumpUrl(), JumpUrlBO.class);
        String type = jumpUrlBO.getType();
        if (Objects.equals(type, JumpType.PROD.value())) {
            Product product = productService.getProductByProdId(Long.valueOf(jumpUrlBO.getLink()));
            if (!Objects.equals(product.getStatus(), ProdStatusEnums.NORMAL.getValue())) {
                throw new YamiShopBindException("跳转商品状态异常，请重新选择");
            }
            return;
        }
        if (Objects.equals(type, JumpType.CATEGORY.value())) {
            List<CategoryLinkBO> linkList = JSON.parseArray(jumpUrlBO.getLink(), CategoryLinkBO.class);
            CategoryLinkBO categoryLinkBO = linkList.get(linkList.size() - 1);
            Category category = categoryService.getCategoryByCategoryId(categoryLinkBO.getValue());
            if (!Objects.equals(category.getStatus(), StatusEnum.ENABLE.value())) {
                throw new YamiShopBindException("跳转分类状态异常，请重新选择");
            }
            return;
        }
        if (Objects.equals(type, JumpType.SHOP.value())) {
            ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(Long.valueOf(jumpUrlBO.getLink()));
            if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OPEN.value())) {
                throw new YamiShopBindException("跳转店铺状态异常，请重新选择");
            }
            return;
        }
        if (Objects.equals(type, JumpType.MINI_PAGE.value())) {
            ShopRenovation shopRenovation = shopRenovationService.getShopRenovationById(Long.valueOf(jumpUrlBO.getLink()));
            if (Objects.isNull(shopRenovation)) {
                throw new YamiShopBindException("跳转微页面状态异常，请重新选择");
            }
            return;
        }
        if (Objects.equals(type, JumpType.COUPON.value())) {
            PopupCouponInfoEvent popupCouponInfoEvent = new PopupCouponInfoEvent(Long.valueOf(jumpUrlBO.getLink()));
            eventPublisher.publishEvent(popupCouponInfoEvent);
            if (!Objects.equals(popupCouponInfoEvent.getStatus(), 1)) {
                throw new YamiShopBindException("跳转优惠券状态异常，请重新选择");
            }
        }
    }

    private static void setTime(CostPerPopup costPerPopup) {
        if (!Objects.equals(costPerPopup.getPushFrequency(), PushFrequencyEnum.CUSTOM.value())) {
            costPerPopup.setWeekFrequency(null);
            costPerPopup.setDayFrequency(null);
        }
        if (costPerPopup.getStartTime().getTime() > System.currentTimeMillis()) {
            costPerPopup.setStatus(PopupStatusEnum.NOT_START.value());
        } else if (costPerPopup.getEndTime().getTime() < System.currentTimeMillis()) {
            costPerPopup.setStatus(PopupStatusEnum.FINISH.value());
        } else {
            costPerPopup.setStatus(PopupStatusEnum.PUT_ON.value());
        }
    }

    private static List<PopupRelate> getPopupRelates(CostPerPopup costPerPopup, List<Long> userLevelIds) {
        List<PopupRelate> popupRelates = new ArrayList<>();
        if (CollUtil.isNotEmpty(userLevelIds)) {
            for (Long userLevelId : userLevelIds) {
                PopupRelate popupRelate = new PopupRelate(costPerPopup.getPopupId(), userLevelId);
                popupRelates.add(popupRelate);
            }
        }
        return popupRelates;
    }

    private List<Long> checkAndGetUserLevelIds(CostPerPopup costPerPopup) {
        List<Long> userLevelIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(costPerPopup.getUserLevelIds())) {
            List<UserLevel> userLevels = userLevelMapper.listUserLevelIds(costPerPopup.getUserLevelIds(), costPerPopup.getShopId());
            if (CollUtil.isEmpty(userLevels)) {
                throw new YamiShopBindException("会员等级均不存在，请重新选择");
            }
            userLevelIds = userLevels.stream().map(UserLevel::getId).collect(Collectors.toList());
        }
        return userLevelIds;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "popup", key = "#costPerPopup.popupId"),
            @CacheEvict(cacheNames = "popupListByShopId", key = "#costPerPopup.shopId")
    })
    public void update(CostPerPopup costPerPopup) {
        CostPerPopup dbPopup = costPerPopupMapper.getByPopupId(costPerPopup.getPopupId());
        if (Objects.isNull(dbPopup)) {
            throw new YamiShopBindException("活动不存在");
        }
        if (Objects.equals(dbPopup.getStatus(), PopupStatusEnum.FINISH.value())) {
            throw new YamiShopBindException("当前活动已结束，无法更新信息");
        }
        setTime(costPerPopup);
        checkJumpUrl(costPerPopup);
        List<Long> userLevelIds = checkAndGetUserLevelIds(costPerPopup);
        costPerPopupMapper.update(costPerPopup);
        List<PopupRelate> popupRelates = getPopupRelates(costPerPopup, userLevelIds);
        popupRelateService.updateBatch(costPerPopup.getPopupId(), popupRelates);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "popup", key = "#popupId"),
            @CacheEvict(cacheNames = "popupListByShopId", key = "#shopId")
    })
    public void deleteById(Long popupId, Long shopId) {
        costPerPopupMapper.deleteById(popupId);
        // 弹窗广告关联商品/会员等级删除
        popupRelateService.deleteById(popupId);
        // 弹窗广告记录删除
        popupUserLogService.removeByPopupId(popupId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "popup", key = "#popupId"),
            @CacheEvict(cacheNames = "popupListByShopId", key = "#shopId")
    })
    public void invalid(Long popupId, Long shopId) {
        costPerPopupMapper.invalid(popupId);
        // 弹窗广告记录删除
        popupUserLogService.removeByPopupId(popupId);
    }

    @Override
    public List<CostPerPopupVO> listByParam(CostPerPopup costPerPopup) {
        return costPerPopupMapper.listByParam(costPerPopup);
    }

    @Override
    public List<Long> putOnAdvertise() {
        List<Long> putOnIds = costPerPopupMapper.listPopUpByStatus(PopupStatusEnum.PUT_ON.value());
        if (CollUtil.isEmpty(putOnIds)) {
            return new ArrayList<>();
        }
        costPerPopupMapper.updateStatus(PopupStatusEnum.PUT_ON.value());
        return putOnIds;
    }

    @Override
    public List<Long> endAdvertise() {
        List<Long> endIds = costPerPopupMapper.listPopUpByStatus(PopupStatusEnum.FINISH.value());
        if (CollUtil.isEmpty(endIds)) {
            return new ArrayList<>();
        }
        costPerPopupMapper.updateStatus(PopupStatusEnum.FINISH.value());
        return endIds;
    }

    @Override
    public List<Long> listShouldChangePopUp() {
        return costPerPopupMapper.listShouldChangePopUp();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePopupByRelate(Long relateThingId, Long shopId) {
        List<CostPerPopup> costPerPopupList = costPerPopupMapper.listNotEndByShopId(shopId);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return;
        }
        // 批量删除关联
        List<Long> deleteIds = new ArrayList<>();
        // 批量更新没有关联等级的弹窗广告为关闭状态
        List<Long> updateIds = new ArrayList<>();
        for (CostPerPopup costPerPopup : costPerPopupList) {
            List<PopupRelate> relateList = popupRelateService.getByPopupId(costPerPopup.getPopupId());
            Map<Long, Long> relateMap = relateList.stream().collect(Collectors.toMap(PopupRelate::getUserLevelId, PopupRelate::getRelateId));
            Long relateId = relateMap.get(relateThingId);
            if (Objects.isNull(relateId)) {
                // 没有关联等级
                continue;
            }
            if (relateMap.keySet().size() == 1) {
                // 只剩下这等级了，将弹窗广告关闭
                updateIds.add(costPerPopup.getPopupId());
            }
            deleteIds.add(relateId);
        }
        if (CollUtil.isNotEmpty(deleteIds)) {
            popupRelateService.deleteByRelateIds(deleteIds);
            removeCacheBatch(deleteIds, Collections.singletonList(shopId));
        }
        if (CollUtil.isNotEmpty(updateIds)) {
            costPerPopupMapper.updateStatusBatch(updateIds);
        }
    }

    @Override
    public void removeCacheBatch(List<Long> popupIds, List<Long> shopIds) {
        List<String> keys = new ArrayList<>(popupIds.size());
        for (Long popupId : popupIds) {
            keys.add("popup" + CacheNames.UNION + popupId);
        }
        for (Long shopId : shopIds) {
            keys.add("popupListByShopId" + CacheNames.UNION + shopId);
        }
        RedisUtil.deleteBatch(keys);
    }

    @Override
    public List<String> getDuplicateList(CostPerPopup costPerPopup, CostPerPopupVO dbCostPerPopup) {
        List<String> weeks = Arrays.stream(costPerPopup.getWeekFrequency().split(StrUtil.COMMA)).toList();
        List<String> dbWeeks = Arrays.stream(dbCostPerPopup.getWeekFrequency().split(StrUtil.COMMA)).toList();
        return dbWeeks.stream().filter(weeks::contains).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteLink(Long linkId, Long shopId, String type, List<Long> categoryIds) {
        List<Long> shopIds = new ArrayList<>();
        shopIds.add(shopId);
        shopIds.add(Constant.PLATFORM_SHOP_ID);
        List<CostPerPopup> costPerPopupList = costPerPopupMapper.listNotEndLinkByShopId(shopIds);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return;
        }
        List<Long> updateIds = new ArrayList<>();
        for (CostPerPopup costPerPopup : costPerPopupList) {
            JumpUrlBO jumpUrlBO = JSON.parseObject(costPerPopup.getJumpUrl(), JumpUrlBO.class);
            if (!Objects.equals(jumpUrlBO.getType(), type)) {
                continue;
            }
            if (Objects.nonNull(linkId) && !Objects.equals(jumpUrlBO.getLink(), String.valueOf(linkId))) {
                continue;
            }
            if (Objects.nonNull(categoryIds) && Objects.equals(type, JumpType.CATEGORY.value())) {
                // [{"label":"2024","value":3887},{"label":"1","value":3888},{"label":"8","value":3899}]
                String categoryStr = jumpUrlBO.getLink();
                List<CategoryLinkBO> linkList = JSON.parseArray(categoryStr, CategoryLinkBO.class);
                CategoryLinkBO categoryLinkBO = linkList.get(linkList.size() - 1);
                if (!categoryIds.contains(categoryLinkBO.getValue())) {
                    continue;
                }
            }
            updateIds.add(costPerPopup.getPopupId());
        }
        if (CollUtil.isNotEmpty(updateIds)) {
            costPerPopupMapper.updateStatusBatch(updateIds);
            removeCacheBatch(updateIds, shopIds);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offlineShop(List<Long> shopIds) {
        List<CostPerPopup> costPerPopupList = costPerPopupMapper.listNotEndLinkByShopId(shopIds);
        if (CollUtil.isEmpty(costPerPopupList)) {
            return;
        }
        List<Long> updateIds = costPerPopupList.stream().map(CostPerPopup::getPopupId).collect(Collectors.toList());
        costPerPopupMapper.updateStatusBatch(updateIds);
        removeCacheBatch(updateIds, shopIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteLinkBatch(List<CouponDto> couponList) {
        Map<Long, List<CouponDto>> couponMap = couponList.stream().collect(Collectors.groupingBy(CouponDto::getShopId));
        List<Long> updateIds = new ArrayList<>();
        Set<Long> shopIdSet = new HashSet<>();
        for (Long shopId : couponMap.keySet()) {
            List<CouponDto> couponDataList = couponMap.get(shopId);
            List<Long> couponIds = couponDataList.stream().map(CouponDto::getCouponId).toList();
            List<Long> shopIds = new ArrayList<>();
            shopIds.add(shopId);
            shopIds.add(Constant.PLATFORM_SHOP_ID);
            List<CostPerPopup> costPerPopupList = costPerPopupMapper.listNotEndLinkByShopId(shopIds);
            if (CollUtil.isEmpty(costPerPopupList)) {
                continue;
            }
            shopIdSet.add(shopId);
            for (CostPerPopup costPerPopup : costPerPopupList) {
                JumpUrlBO jumpUrlBO = JSON.parseObject(costPerPopup.getJumpUrl(), JumpUrlBO.class);
                if (!Objects.equals(jumpUrlBO.getType(), JumpType.COUPON.value())) {
                    continue;
                }
                if (!couponIds.contains(Long.valueOf(jumpUrlBO.getLink()))) {
                    continue;
                }
                updateIds.add(costPerPopup.getPopupId());
            }
        }
        shopIdSet.add(Constant.PLATFORM_SHOP_ID);
        if (CollUtil.isNotEmpty(updateIds)) {
            costPerPopupMapper.updateStatusBatch(updateIds);
            removeCacheBatch(updateIds, new ArrayList<>(shopIdSet));
        }
    }
}
